package com.admin.security;

import com.admin.domain.model.Role;
import com.admin.domain.model.User;
import com.admin.domain.repository.RoleRepository;
import com.admin.domain.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;


/**
 * AuthenticationManager使用AuthenticationProvider来认证用户。
 * AuthenticationProvider使用UserDetailsService来获取用户信息！
 *
 * TODO 在认证的时候，应该将角色、权限都放入authentication对象中！这里只放了权限。
 *
 * @author Jonsy
 */
@Service
public class UserDetailService implements UserDetailsService {

    @Autowired
    protected UserRepository userRepository;

    @Autowired
    protected RoleRepository roleRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        User user = userRepository.findByUserName(username);
        if(user == null){
            throw new UsernameNotFoundException("no user");
        }
        SecurityUser userDetails = new SecurityUser(user.getId(),
                                                    username,
                                                    user.getPassword(),
                                                    !user.isDisabled(),
                                                    true,
                                                    true,
                                                    true,
                                                    grantedAuthorities(user.getId()),
                                                    user.getSalt(),
                                                    user.getEmail());
        return userDetails;
    }

    /**
     * 根据用户id查找其拥有的角色，再将所有角色的权限作为集合返回。
     * TODO 这样的话，只有认证的时候才会加载用户的权限集合，新增的权限是无法更新的，除非重新登陆！
     * TODO 或者，调用authentication的authorities，将新的权限添加进去。
     *
     * @param userId
     * @return
     */
    protected Collection<GrantedAuthority> grantedAuthorities(String userId){
        List<Role> resources = roleRepository.getRoles(userId);
        if(CollectionUtils.isEmpty(resources)){
            return new ArrayList<>();
        }
        Collection<GrantedAuthority> authorities = new HashSet<>();
        //TODO 忽略已经禁用的角色
        resources.stream().filter(role -> !role.isDisabled()).forEach((resource -> {
            authorities.add(new SimpleGrantedAuthority(resource.getName()));
        }));
        return authorities;
    }

}
